package at.technikumwien.trackmydevice.at.technikumwien.trackmydevice;

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.HandlerThread;
import android.os.IBinder;
import android.widget.RemoteViews;
import android.widget.Toast;
import at.technikumwien.trackmydevice.R;

public class TrackingService extends Service {
	
	private String logKey_cur = null;
	private String logName_cur = null;
	private static final int TWO_MINUTES = 1000 * 60 * 2;
	private static long INTERVAL = 0;
	public final int TRACKING_ID = 99;
	private NotificationManager mNM = null;
	private LocationManager locManager = null;
	private LocationListener locListener = null;
	private Location LocationStorage = null;
	private DataBaseHandler db_handling = null;
	private SQLiteDatabase storeDB = null;
	private Date checkTime = null;
	Notification showInStatus= null;
	private HandlerThread backgroundThread;
	private Cursor query_history_result = null;
	private Timer handle_intervalled_updatesTimer = null;
	private TimerTask updateLocationTask = null;
	
	public TrackingService (int interval)
	{
		INTERVAL = interval;		
	}

	@Override
	public void onCreate()
	{
		//Set the interval
		updateLocationTask = new TimerTask()
		{
			@Override
			public void run() {
				// TODO Auto-generated method stub
				locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locListener);
				locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locListener);
				locManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0, locListener);
			}
			
		};
		handle_intervalled_updatesTimer = new Timer("loc_update_timer");
		handle_intervalled_updatesTimer.schedule(updateLocationTask, 0, INTERVAL);
		//Initiate the DBHandler class
		db_handling = new DataBaseHandler(this);
		//Get TimeStamp
		checkTime = new Date();
		//Setup the notifier view
		RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notify_view);
		contentView.setImageViewResource(R.id.image, R.drawable.icon);
		contentView.setTextViewText(R.id.text, "Tracking active. Touch here to stop!");
		//First setup the parallel Thread
		//backgroundThread = new HandlerThread("ServiceStartArguments", android.os.Process.THREAD_PRIORITY_BACKGROUND);
		//Notification settings
		Context appContext = getApplicationContext();
		String ns = Context.NOTIFICATION_SERVICE;
		mNM = (NotificationManager) getSystemService(ns);
		Intent notificationIntent = new Intent(this, startup.class);
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
		showInStatus = new Notification();
		showInStatus.icon = R.drawable.icon_status;
		showInStatus.ledARGB = Color.BLUE;
		showInStatus.ledOffMS = 300;
		showInStatus.ledOnMS = 600;
		showInStatus.tickerText = "Tracking active";
		showInStatus.flags = Notification.FLAG_ONGOING_EVENT;
		showInStatus.flags |= Notification.FLAG_NO_CLEAR;
		showInStatus.flags |= Notification.FLAG_SHOW_LIGHTS;
		showInStatus.when = System.currentTimeMillis();
		showInStatus.setLatestEventInfo(appContext, "TMD notification", "Tracking active", contentIntent);
		//Setup of the location manager
		locManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
		//Setup of the DataBasestorage
		storeDB = db_handling.getWritableDatabase();
	}
	
	@Override
	public void onStart(Intent intent, int startId)
	{
		//This is where the fun begins
		Calendar getDateCal = Calendar.getInstance();
		checkTime = getDateCal.getTime();
		//Notification shown
		mNM.notify(TRACKING_ID, showInStatus);
		locListener = new LocationListener()
		{
			public void onLocationChanged(Location loc)
			{
				//Called when a new location is found by the location provider
				
				if (isBetterLocation(loc, LocationStorage))
				{
					LocationStorage = loc;
					ContentValues loc_content = new ContentValues();
					loc_content.put("timestamp", String.valueOf(checkTime));
					loc_content.put("log_key", logKey_cur);
					loc_content.put("longitude", String.valueOf(loc.getLongitude()));
					loc_content.put("latitude", String.valueOf(loc.getLatitude()));
					loc_content.put("speed", String.valueOf(loc.getSpeed()));
					loc_content.put("alt", String.valueOf(loc.getAltitude()));
					storeDB.insert(db_handling.POSITION_TABLE_NAME, null, loc_content);
				}
			}
			
			
			public void onProviderEnabled(String provider)
			{
				
			}
			
			public void onProviderDisabled(String provider)
			{
				
			}

			public void onStatusChanged(String provider, int status,
					Bundle extras) {
				// TODO Auto-generated method stub
				
			}
		};
		
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId)
	{
		 // We want this service to continue running until it is explicitly
	    // stopped, so return sticky.
		Toast.makeText(this, "tracking starting", Toast.LENGTH_SHORT).show();
		//This is where the fun begins
		//Start Background Thread
		backgroundThread.start();
		//Notification shown
		mNM.notify(TRACKING_ID, showInStatus);
		locListener = new LocationListener()
		{
			public void onLocationChanged(Location loc)
			{
				//Called when a new location is found by the location provider

				if (isBetterLocation(loc, LocationStorage))
				{
					LocationStorage = loc;
					ContentValues loc_content = new ContentValues();
					loc_content.put("timestamp", String.valueOf(checkTime));
					loc_content.put("log_key", logKey_cur);
					loc_content.put("longitude", String.valueOf(loc.getLongitude()));
					loc_content.put("latitude", String.valueOf(loc.getLatitude()));
					loc_content.put("speed", String.valueOf(loc.getSpeed()));
					loc_content.put("alt", String.valueOf(loc.getAltitude()));
					storeDB.insert(db_handling.POSITION_TABLE_NAME, null, loc_content);
				}
			}
			
			
			public void onProviderEnabled(String provider)
			{
				
			}
			
			public void onProviderDisabled(String provider)
			{
				
			}

			public void onStatusChanged(String provider, int status,
					Bundle extras) {
				// TODO Auto-generated method stub
				
			}
		};
		locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locListener);
		locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locListener);
		locManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0, locListener);
	    return START_STICKY;
	}
	
	@Override
	public void onDestroy()
	{
		Toast.makeText(this, "tracking stopping", Toast.LENGTH_SHORT).show();
		//make sure all notifications are gone
		locManager.removeUpdates(locListener);
		mNM.cancel(TRACKING_ID);
	}
	
	/** Determines whether one Location reading is better than the current Location fix
	  * @param location  The new Location that you want to evaluate
	  * @param currentBestLocation  The current Location fix, to which you want to compare the new one
	  */
	protected boolean isBetterLocation(Location location, Location currentBestLocation) {
	    if (currentBestLocation == null) {
	        // A new location is always better than no location
	        return true;
	    }

	    // Check whether the new location fix is newer or older
	    long timeDelta = location.getTime() - currentBestLocation.getTime();
	    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
	    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
	    boolean isNewer = timeDelta > 0;

	    // If it's been more than two minutes since the current location, use the new location
	    // because the user has likely moved
	    if (isSignificantlyNewer) {
	        return true;
	    // If the new location is more than two minutes older, it must be worse
	    } else if (isSignificantlyOlder) {
	        return false;
	    }

	    // Check whether the new location fix is more or less accurate
	    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
	    boolean isLessAccurate = accuracyDelta > 0;
	    boolean isMoreAccurate = accuracyDelta < 0;
	    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

	    // Check if the old and new location are from the same provider
	    boolean isFromSameProvider = isSameProvider(location.getProvider(),
	            currentBestLocation.getProvider());

	    // Determine location quality using a combination of timeliness and accuracy
	    if (isMoreAccurate) {
	        return true;
	    } else if (isNewer && !isLessAccurate) {
	        return true;
	    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
	        return true;
	    }
	    return false;
	}

	/** Checks whether two providers are the same */
	private boolean isSameProvider(String provider1, String provider2) {
	    if (provider1 == null) {
	      return provider2 == null;
	    }
	    return provider1.equals(provider2);
	}

	
	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}
	
	public void InsertTrackingInfoToDB (String name, String logKey)
	{
		//Search in Database for name
		SQLiteDatabase myDB = null;
		myDB = SQLiteDatabase.openDatabase(DataBaseHandler.DATABASE_NAME, null, SQLiteDatabase.CREATE_IF_NECESSARY);
		if(myDB.isOpen())
		{
						
		}
	}
	
	
    public boolean query_locDB ()
    {
    	boolean success = false;
    	try
    	{
    		SQLiteDatabase queryDB = db_handling.getReadableDatabase();
    		if (queryDB.isOpen())
    		{
    			String[] selected_columns = {"id", "log_name"};
    			query_history_result = queryDB.query(DataBaseHandler.HISTORY_TABLE_NAME, selected_columns, null, null, null, null, "id");
    			query_history_result.close();
    			//queryDB.close();
    			success = true;
    		}
    	}
    	catch (SQLException myExcept) {success = false;}
    	return success;
    }
}
